package com.pengpeng.zookeeper.service.impl;

import com.pengpeng.zookeeper.service.ZookeeperService;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 彭鹏
 * @date 2021/10/21.
 */
@Service
@Slf4j
public class ZookeeperServiceImpl implements ZookeeperService {

    @Autowired
    private ZooKeeper zookeeper;

    /**
     * 创建znode结点
     *
     * @param path 结点路径
     * @param data 结点数据
     * @return true 创建结点成功 false表示结点存在
     */
    @Override
    public boolean addNodeData(String path, String data, CreateMode mode) {
        try {
            if (zookeeper.exists(path, true) == null) {
                zookeeper.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
                return true;
            }
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("创建znode：" + path + "出现问题！！", e);
        }
        System.out.println("znode" + path + "结点已存在");
        return false;
    }

    /**
     * 创建永久znode结点
     *
     * @param path 结点路径
     * @param data 结点数据
     * @return true 创建结点成功 false表示结点存在
     */
    @Override
    public boolean addPNode(String path, String data) {
        return addNodeData(path, data, CreateMode.PERSISTENT);
    }

    /**
     * 创建临时znode结点
     *
     * @param path 结点路径
     * @param data 结点数据
     * @return true 创建结点成功 false表示结点存在
     */
    @Override
    public boolean addENode(String path, String data) {
        return addNodeData(path, data, CreateMode.EPHEMERAL);
    }

    /**
     * 修改znode
     *
     * @param path 结点路径
     * @param data 结点数据
     * @return 修改结点成功   false表示结点不存在
     */
    @Override
    public boolean updateNode(String path, String data) {
        try {
            Stat stat = null;
            if ((stat = zookeeper.exists(path, true)) != null) {
                zookeeper.setData(path, data.getBytes(), stat.getVersion());
                return true;
            }
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("修改znode：" + path + "出现问题！！", e);
        }
        return false;
    }

    /**
     * 删除结点
     *
     * @param path 结点
     * @return true 删除键结点成功  false表示结点不存在
     */
    @Override
    public boolean deleteNode(String path) {
        try {
            Stat stat = null;
            if ((stat = zookeeper.exists(path, true)) != null) {
                List<String> subPaths = zookeeper.getChildren(path, false);
                if (subPaths.isEmpty()) {
                    zookeeper.delete(path, stat.getVersion());
                    return true;
                } else {
                    for (String subPath : subPaths) {
                        deleteNode(path + "/" + subPath);
                    }
                }
            }
        } catch (InterruptedException | KeeperException e) {
            throw new RuntimeException("删除znode：" + path + "出现问题！！", e);
        }
        return false;
    }

    /**
     * 取到结点数据
     *
     * @param path 结点路径
     * @return null表示结点不存在 否则返回结点数据
     */
    @Override
    public String getNodeData(String path) {
        String data = null;
        try {
            Stat stat = null;
            if ((stat = zookeeper.exists(path, true)) != null) {
                data = new String(zookeeper.getData(path, true, stat));
            } else {
                System.out.println("node:" + path + ",不存在");
                log.info("node:{},不存在",path);
            }
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("取到znode：" + path + "出现问题！！", e);
        }
        return data;
    }
    @Override
    public List<String> getChildrenNode(String path, boolean nodeWatch)  {
        List<String> childrenList = null;
        try {
            childrenList = zookeeper.getChildren(path, nodeWatch);
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("getChildrenNode：" + path + "出现问题！！", e);
        }
        return childrenList;
    }

    @Override
    public List<String> getChildrenNode(String path, Watcher watcher){
        List<String> childrenList = null;
        try {
            childrenList = zookeeper.getChildren(path, watcher);
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("getChildrenNode：" + path + "出现问题！！", e);
        }
        return childrenList;
    }
    @Override
    public Stat existNode(String path, boolean nodeWatch) {
        Stat exists = null;
        try {
            exists = zookeeper.exists(path, nodeWatch);
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("判斷node是否存在：" + path + "出现问题！！", e);
        }
        return exists;
    }

    @Override
    public Stat existNode(String path, Watcher watcher) {
        Stat exists = null;
        try {
            exists = zookeeper.exists(path, watcher);
        } catch (KeeperException | InterruptedException e) {
            throw new RuntimeException("判斷node是否存在：" + path + "出现问题！！", e);
        }
        return exists;
    }
}